package com.hyd.hx_adr.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hyd.hx_adr.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;

/**
 * @author van
 * @create 2022/4/28 15:49
 */
@Slf4j
public class ImportExcelUtils {

    /**
     *
     * @param file 前端传入Excel文件
     * @param clazz 对应excel的解析类
     * @param line 从第几行开始读取数据
     */
    public static <T> List<T> getListData(MultipartFile file, Class clazz,int line) throws IOException {
        isExcel(file);
        List<Object> list = EasyExcel.read(file.getInputStream(), clazz, new AnalysisEventListener() {
            @Override
            public void invoke(Object o, AnalysisContext analysisContext) {
                System.out.println("读取数据:"+o);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                System.out.println("excel文件读取结束");
            }
        }).sheet().headRowNumber(line).doReadSync();
        return transfer(list,clazz);
    }
    /**
     * 含有合并单元格数据
     * @param file 前端传入Excel文件
     * @param clazz 对应excel的解析类
     * @param line 从第几行开始读取数据
     * columns excel中含有合并单元格的字段
     */
    public static <T> List<T> getComplexListData(MultipartFile file, Class clazz,int line,List<String> columns) throws IOException {
        List<Object> extraList = new CopyOnWriteArrayList<>();
        isExcel(file);
        EasyExcel.read(file.getInputStream(), clazz, new AnalysisEventListener() {
            @Override
            public void invoke(Object o, AnalysisContext analysisContext) {
                extraList.add(o);
                System.out.println("读取数据:"+o);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                System.out.println("excel文件读取结束");
            }

            @Override
            public void extra(CellExtra extra, AnalysisContext context) {
                Object o = extraList.get(extra.getRowIndex()>0?extra.getRowIndex()-2:extra.getRowIndex());
                if(!columns.isEmpty()){
                    columns.forEach(column->{
                        try {
                            Field field = o.getClass().getDeclaredField(column);
                            field.setAccessible(true);
                            Object value = field.get(o);
                            List<Object> objects = extraList.subList(extra.getRowIndex()>0?extra.getRowIndex()-2:extra.getRowIndex()
                                    , extra.getLastRowIndex()>0?extra.getLastRowIndex()-1:extra.getLastRowIndex());
                            objects.forEach(item->{
                                try {
                                    Field declaredField = item.getClass().getDeclaredField(column);
                                    declaredField.setAccessible(true);
                                    declaredField.set(item,value);
                                } catch (NoSuchFieldException | IllegalAccessException e) {
                                    throw new BusinessException("未获取到该字段!");
                                }
                            });
                        } catch (NoSuchFieldException e) {
                            throw new BusinessException("未获取到该字段!");
                        } catch (IllegalAccessException e) {
                            throw new BusinessException("未获取到该字段的值!");
                        }
                    });
                }
            }
        }).extraRead(CellExtraTypeEnum.MERGE).sheet().headRowNumber(line).doReadSync();
        return transfer(extraList,clazz);
    }

    public static <T> void exportExcel(List<T> list,Class clazz,String fileName,String sheetName){
        Consumer<ExcelWriter> consumer = writer -> {
            writer.write(list, EasyExcel.writerSheet(sheetName==null?"excel":sheetName)
                    .head(clazz)
                    .build());
        };
        ExcelWriter build = EasyExcel.write(fileName).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
        consumer.accept(build);
        build.finish();
    }

    private static <T> List<T> transfer(List<Object> list ,Class<T> clazz)  {
        if(list==null||list.isEmpty()){
            throw new BusinessException("传入数据为空!");
        }
        List<T> result = new ArrayList<>();

        ObjectMapper objectMapper = new ObjectMapper();
        list.forEach(item->{
            try{
                T t = objectMapper.convertValue(item, clazz);
                result.add(t);
            }catch (Exception e){
                e.printStackTrace();
            }
        });
        return result;
    }

    private static void isExcel(MultipartFile file){
        final String filename = file.getResource().getFilename();
        int i = filename.lastIndexOf(".");
        String substring = filename.substring(i+1);
        if(StringUtils.isBlank(substring)){
            throw new BusinessException("无法解析该类型!");
        }
        if(!substring.equals("xls")&&!substring.equals("xlsx")){
            throw new BusinessException("只能解析excel表格!");
        }
    }

}
